package com.service.login.druid;

/**
 * @author
 * @version 1.0
 * @date 2021/4/28 14:47
 */

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.service.login.datasource.DynamicDataSource;
import com.service.login.enums.DataSourceType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 数据源配置类
 */
@Configuration
@MapperScan(basePackages = {DataSourceConfiguration.MAPPER_INTERFACE_PACKAGE}, sqlSessionTemplateRef = "sqlSessionTemplate")
public class DataSourceConfiguration {
    @Autowired
    private Environment env;
    /**
     * 扫描的mapper接口路径
     */
    public static final String MAPPER_INTERFACE_PACKAGE = "com.service.login.dao";
    /**
     * 扫描的mapper文件路径
     */
    public static final String MAPPER_XML_PACKAGE = "classpath:mapper/*.xml";
    /**
     * 主库
     */
    @Bean("master")
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource() {
        DruidDataSource build = DruidDataSourceBuilder.create().build();
        build.setName("master");//数据源名称
        return build;
    }


    /**
     * 从库
     */
    @Bean("slave")
    @ConditionalOnProperty( prefix = "spring.datasource.druid.slave", name = "enable", havingValue = "true")//是否开启数据源开关---若不开启 默认适用默认数据源
    @ConfigurationProperties("spring.datasource.druid.slave")
    public DataSource slaveDataSource() {
        DruidDataSource build = DruidDataSourceBuilder.create().build();
        build.setName("slave");//数据源名称
        return build;
    }
    /**
     * 初始化动态数据源,并注入db01,db02,以及设置默认数据源为db01
     */
    @Bean
    public DynamicDataSource dynamicDataSource(@Qualifier("master") DataSource master, @Qualifier("slave") DataSource slave) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> map = new HashMap<>();
        map.put("master", master);
        map.put("slave", slave);
        //默认数据源
        //dynamicDataSource.setDefaultTargetDataSource(master);
        //数据源列表,与名称绑定
        dynamicDataSource.setTargetDataSources(map);
        return dynamicDataSource;
    }

    /**
     * 配置 SqlSessionFactoryBean
     * 将 MyBatis 的 mapper 位置和持久层接口的别名设置到 Bean 的属性中，如果没有使用 *.xml 则可以不用该配置，否则将会产生 invalid bond statement 异常
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        // 配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource 作为数据源则不能实现切换
        bean.setDataSource(dynamicDataSource);
        //此处设置为了解决找不到mapper文件的问题
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_XML_PACKAGE));
        return bean.getObject();
    }

    /**
     * 设置动态数据源DynamicDataSource到会话工厂
     */
    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
    @Bean
    public PlatformTransactionManager platformTransactionManager(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

}
